package com.varian.system.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.varian.mybatis.base.BaseServiceImpl;
import com.varian.mybatis.util.PageUtil;
import com.varian.redis.util.RedisUtil;
import com.varian.service.constant.ServiceConstant;
import com.varian.system.constant.SystemConstant;
import com.varian.system.convert.SystemConvert;
import com.varian.system.dto.SysParamDTO;
import com.varian.system.dto.SysParamPageDTO;
import com.varian.system.entity.SysParam;
import com.varian.system.mapper.SysParamMapper;
import com.varian.system.service.ISysParamService;
import com.varian.system.vo.SysParamVO;
import com.varian.tool.enums.CommonStatusEnum;
import com.varian.tool.exception.BizException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author ben
 * @since 2025/2/9
 */
@Service
@RequiredArgsConstructor
public class SysParamServiceImpl extends BaseServiceImpl<SysParamMapper, SysParam> implements ISysParamService {

    private final SystemConvert baseConvert;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(SysParamDTO dto) {
        SysParam param = baseConvert.toEntity(dto);
        validateUniqueness(param);
        boolean result = save(param);
        if (result) {
            String key = ServiceConstant.SYS_PARAM_KEY.format(param.getParamCode());
            RedisUtil.Value.set(key, dto.getParamValue());
        }
        return result;
    }

    @Override
    public Page<SysParamVO> page(SysParamPageDTO dto) {
        Page<SysParam> page = page(dto.toPage(), lambdaQuery().getWrapper()
                .likeRight(StrUtil.isNotBlank(dto.getParamCode()), SysParam::getParamCode, dto.getParamCode())
                .eq(dto.getParamType() != null, SysParam::getParamType, dto.getParamType())
                .eq(dto.getParamStatus() != null, SysParam::getParamStatus, dto.getParamStatus())
                .orderByDesc(SysParam::getId));
        return PageUtil.convert(page, baseConvert::toVO);
    }

    @Override
    public SysParamVO detail(Long id) {
        SysParam param = validateExistence(id);
        return baseConvert.toVO(param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean modify(Long id, SysParamDTO dto) {
        validateExistence(id);
        SysParam param = baseConvert.toEntity(id, dto);
        validateUniqueness(param);
        boolean result = updateById(param);
        if (result) {
            String key = ServiceConstant.SYS_PARAM_KEY.format(param.getParamCode());
            if (CommonStatusEnum.ENABLED.equals(dto.getParamStatus())) {
                RedisUtil.Value.set(key, dto.getParamValue());
            } else if (CommonStatusEnum.DISABLED.equals(dto.getParamStatus())) {
                RedisUtil.del(key);
            }
        }
        return result;
    }

    @Override
    public boolean delete(Long id) {
        SysParam param = validateExistence(id);
        boolean result = removeById(param.getId());
        if (result) {
            String key = ServiceConstant.SYS_PARAM_KEY.format(param.getParamCode());
            RedisUtil.del(key);
        }
        return result;
    }

    @Override
    protected SysParam validateExistence(Long id) {
        SysParam param = baseMapper.selectById(id);
        Assert.notNull(param, () -> BizException.of(SystemConstant.PARAM_NOT_EXIST));
        return param;
    }

    @Override
    protected void validateUniqueness(SysParam param) {
        boolean existed = baseMapper.exists(lambdaQuery().getWrapper()
                .eq(SysParam::getParamCode, param.getParamCode())
                .ne(param.getId() != null, SysParam::getId, param.getId()));
        Assert.isFalse(existed, () -> BizException.of(SystemConstant.PARAM_EXIST, param.getParamCode()));
    }
}
